package com.runa.monitor.platinterface.extend.hmy;

import com.alibaba.fastjson.JSON;
import com.rn.smart.command.dto.valve.ValveBase;
import com.rn.smart.command.dto.valve.contro.HeiMaYiValve;
import com.runa.monitor.comm.dto.newComm.AsynResult;
import com.runa.monitor.comm.dto.newComm.ValveVO;
import com.runa.monitor.comm.entity.CommValve;
import com.runa.monitor.platinterface.mqtt.MqttUtil;
import com.runa.persistence.DateUtil;
import com.runa.persistence.service.CommValveService;
import com.runa.rccprotocol.http.HttpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 2024/10/18 9:19
 * zhangYB
 */
@Slf4j
@Service
public class HmyValveService {


    @Value("${hmy.appId:}")
    private String appId;
    @Value("${hmy.appKey:}")
    private String appKey;
    @Value("${hmy.control.workModeUrl:}")
    private String workModeUrl;
    @Value("${hmy.control.valveOpenUrl:}")
    private String valveOpenUrl;
    @Value("${hmy.control.returnTempUrl:}")
    private String returnTempUrl;
    @Value("${hmy.control.roomTempUrl:}")
    private String roomTempUrl;

    @Resource
    private HttpService httpService;

    @Resource
    private CommValveService commValveService;

    public static void main(String[] args) {
        HmyValveService hmyValveService = new HmyValveService();
        String s = hmyValveService.accessToken("CESHI", "cs2024", "2024060817240000");
        System.out.println(s);
        s = hmyValveService.authorization("CESHI", "2024060817240000");
        System.out.println(s);
    }

    public void send(List<HeiMaYiValve> heiMaYiValves, String task, String holdInfo, Integer priority, String mode, String url, HttpMethod httpMethod) {
        log.debug("{} {} {} {} {} {} {}", task, holdInfo, priority, mode, url, httpMethod, JSON.toJSONString(heiMaYiValves));
        Map<String, CommValve> commValveMap = batchQueryValve(task, holdInfo, heiMaYiValves);
        for (HeiMaYiValve heiMaYiValve : heiMaYiValves) {
            CommValve commValve = commValveMap.get(heiMaYiValve.getNodeId());
            if (null == commValve) {
                continue;
            }
            heiMaYiValve.setMsgId(heiMaYiValve.getMsgId() == 0 ? 1 : heiMaYiValve.getMsgId());
            HmyValveOpenRequest request = new HmyValveOpenRequest(heiMaYiValve.getMsgId(), commValve.getSerial(), heiMaYiValve.getExpiredDate(), heiMaYiValve.getValue());
            HmyRequestParam hmyRequestParam = new HmyRequestParam(commValve, heiMaYiValve, mode, url, httpMethod, request);
            hmyRequestParam.setTask(task);
            hmyRequestParam.setHoldInfo(holdInfo);
            hmyRequestParam.setPriority(priority);
            request(hmyRequestParam);
        }

    }

    public void send(List<ValveBase> valveBases, String task, String holdInfo, Integer priority) {
        log.debug("{} {} {} {}", task, holdInfo, priority, JSON.toJSONString(valveBases));
        Map<String, List<HeiMaYiValve>> typeMap = getTypeMap(valveBases);
        for (String type : typeMap.keySet()) {
            switch(type) {
                case "开度":
                    send(typeMap.get(type), task, holdInfo, priority, "132", valveOpenUrl, HttpMethod.POST);
                    break;
                case "通断":
                    send(typeMap.get(type), task, holdInfo, priority, "129", valveOpenUrl, HttpMethod.POST);
                    break;
                case "室温":
                    send(typeMap.get(type), task, holdInfo, priority, "131", roomTempUrl, HttpMethod.POST);
                    break;
                case "回温":
                    send(typeMap.get(type), task, holdInfo, priority, "130", returnTempUrl, HttpMethod.POST);
                    break;
            }

        }
    }



    public Map<String, CommValve> batchQueryValve(String taskNo, String holdInfo, List<HeiMaYiValve> heiMaYiValves) {
        ArrayList<String> nodeIds = new ArrayList<>(heiMaYiValves.stream().map(HeiMaYiValve::getNodeId).distinct().collect(Collectors.toList()));
        List<CommValve> valves = commValveService.getAllByIds(nodeIds);

        List<String> valveIds = valves.stream().map(CommValve::getId).collect(Collectors.toList());
        for (String valveId : valveIds) {
            nodeIds.remove(valveId);
        }

        if (!nodeIds.isEmpty())
            nodeIds.forEach(s -> MqttUtil.sendOfWithoutArchive(taskNo, holdInfo, ValveVO.TOPIC, s));

        if (valves.isEmpty()) return new HashMap<>();
        return valves.stream().collect(Collectors.toMap(CommValve::getId, Function.identity()));
    }

    public Map<String, List<HeiMaYiValve>> getTypeMap(List<ValveBase> valveBases) {
        Map<String, List<HeiMaYiValve>> typeMap = new HashMap<>();
        for (ValveBase valveBase : valveBases) {
            if (!(valveBase instanceof HeiMaYiValve)) {
                log.error("黑蚂蚁抄阀参数错误: {}", JSON.toJSONString(valveBase));
                continue;
            }
            HeiMaYiValve heiMaYiValve = (HeiMaYiValve)valveBase;
            List<HeiMaYiValve> heiMaYiValves = typeMap.get(heiMaYiValve.getType());
            if (null == heiMaYiValves) {
                heiMaYiValves = new ArrayList<>();
                typeMap.put(heiMaYiValve.getType(), heiMaYiValves);
            }
            heiMaYiValves.add(heiMaYiValve);
        }
        return typeMap;
    }


    private boolean workModeRequest(Long msgId, String nodeId, String expiredDate, String mode) {
        HmyValveWorkModeRequest workModeRequest = new HmyValveWorkModeRequest(msgId, nodeId, expiredDate, mode);
        HmyResponse response = request(workModeUrl, HttpMethod.POST, workModeRequest);
        if (null == response) {
            return false;
        }
        if (!response.isSuccess()) {
            log.error("工作模式下发失败: {}  {}  {}  {}  {} ", msgId, nodeId, expiredDate, mode, JSON.toJSONString(response));
        }
        log.debug("工作模式下发成功: {}  {}  {}  {}  {} ", msgId, nodeId, expiredDate, mode, JSON.toJSONString(response));
        return response.isSuccess();
    }


    private void request(HmyRequestParam hmyRequestParam) {
        HeiMaYiValve heiMaYiValve = hmyRequestParam.getHeiMaYiValve();
        if (workModeRequest(heiMaYiValve.getMsgId(), hmyRequestParam.getCommValve().getSerial(), heiMaYiValve.getExpiredDate(), hmyRequestParam.getMode())) {
            HmyResponse response = request(valveOpenUrl, HttpMethod.POST, hmyRequestParam.getHmyRequest());
            if (!response.isSuccess()) {
                log.error("请求: {} 失败", valveOpenUrl, JSON.toJSONString(hmyRequestParam.getHmyRequest()));
                return;
            }
            log.debug("请求: {} 成功", valveOpenUrl, JSON.toJSONString(hmyRequestParam.getHmyRequest()));
            AsynResult asynResult = AsynResult.success();
            asynResult.setIdentity(hmyRequestParam.getCommValve().getId());
            asynResult.setTask(hmyRequestParam.getTask());
            asynResult.setHoldInfo(hmyRequestParam.getHoldInfo());
            asynResult.setTimestamp(System.currentTimeMillis());
            log.debug("上报: {}", JSON.toJSONString(asynResult));
            MqttUtil.send(MqttUtil.topicOfNoneContentForNode, asynResult);
        }

    }

    public HmyResponse request(String url, HttpMethod httpMethod, Object body) {
        try {
            String timestamp = DateUtil.nowToString("yyyyMMddHH24mmss");
            HttpHeaders httpHeaders = new HttpHeaders();
            String accessToken = accessToken(timestamp);
            String authorization = authorization(timestamp);
            httpHeaders.add("AccessToken", accessToken);
            httpHeaders.add("Authorization", authorization);
            HttpEntity httpEntity = new HttpEntity(body, httpHeaders);
            ResponseEntity<HmyResponse> responseEntity = httpService.exchange(url, httpMethod, httpEntity, HmyResponse.class);
            log.debug("request: {} {} {} {} {} {}", accessToken, authorization, url, httpMethod, JSON.toJSONString(body), responseEntity);
            HttpStatus statusCode = responseEntity.getStatusCode();
            if (!statusCode.is2xxSuccessful()) {
                log.error("request: {} {} {} {}", url, httpMethod, JSON.toJSONString(httpEntity), JSON.toJSONString(responseEntity));
                return null;
            }
            return responseEntity.getBody();
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }


    private String accessToken(String timestamp) {
        return accessToken(appId, appKey, timestamp);
    }

    private String accessToken(String appId, String appKey, String timestamp) {
        return DigestUtils.md5DigestAsHex((appId + appKey + timestamp).getBytes());
    }

    private String authorization(String timestamp) {
        return authorization(appId, timestamp);
    }

    private String authorization(String appId, String timestamp) {
        return Base64Utils.encodeToString((appId + ":" + timestamp).getBytes());
    }







}
